package com.zsg.androidsipphone;

import android.Manifest;
import android.app.Activity;
import android.app.Dialog;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.sip.*;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.zsg.androidsipphone.sip.IncomingCallReceiver;
import com.zsg.androidsipphone.sip.SipSettings;
import com.zsg.androidsipphone.ui.fragment.CenterFragment;
import com.zsg.androidsipphone.ui.fragment.EndFragment;
import com.zsg.androidsipphone.ui.fragment.StartFragment;
import com.zsg.androidsipphone.util.Api;
import com.zsg.androidsipphone.util.MySystemUtil;

import java.text.ParseException;

/**
 * @author zsg
 * @date 2020/9/7
 */
public class MainActivity extends AppCompatActivity {

    private static BottomNavigationView navigationView;

    private static Fragment[] fragments;
    private int lastFragment;

    public SipManager manager = null;
    private SipProfile me = null;
    private SipAudioCall call = null;
    private IncomingCallReceiver callReceiver;

    private static final int REGISTER_AGAIN = 1;
    private static final int SET_AUTH_INFO = 2;
    private static final int UPDATE_SETTINGS_DIALOG = 3;
    private static final int HANG_UP = 4;

    private static final String TAG = "SipActivity";
    /**
     * 申请sip权限
     */
    private static final String[] PERMISSION_SIP = { Manifest.permission.USE_SIP
    };
    /**
     * 申请录音权限
     */
    private static final String[] PERMISSION_AUDIO = { Manifest.permission.RECORD_AUDIO
    };
    /**
     * 申请sdk权限
     */
    private static final String[] PERMISSION_SDK = { Manifest.permission.WRITE_EXTERNAL_STORAGE
    };


    /**
     * Fragment切换方法
     * @param lastFragment 上一个被选择的Fragment
     * @param nextFragment 即将跳转到的Fragment
     */
    private void switchFragment(int lastFragment,int nextFragment){
        //取得FragmentTransaction
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        //隐藏上一个Fragment
        transaction.hide(fragments[lastFragment]);
        //将Fragment添加到FragmentTransaction
        if(!fragments[nextFragment].isAdded()){
            transaction.add(R.id.nav_host_frameLayout,fragments[nextFragment]);
        }
        //显示下一个Fragment
        transaction.show(fragments[nextFragment]).commit();
    }

    /**
     * 底部菜单栏监听处理
     */
    private final BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
            = item -> {
        switch (item.getItemId()) {
            case R.id.navigation_dialer_sip:
                if(lastFragment != 0){
                    switchFragment(lastFragment,0);
                    lastFragment = 0;
                }
                return true;
            case R.id.navigation_account_box:
                if(lastFragment != 1){
                    switchFragment(lastFragment,1);
                    lastFragment = 1;
                }
                return true;
            case R.id.navigation_person_center:
                if(lastFragment != 2){
                    switchFragment(lastFragment,2);
                    lastFragment = 2;
                }
                return true;
            default:
                break;
        }
        return false;
    };


    /**
     * sip注册监听
     */
    private final SipRegistrationListener registrationListener = new SipRegistrationListener() {

        @Override
        public void onRegistering(String s) {
            updateStatus("Registering with SIP Server...");
            Log.e(TAG, "onRegistering: "+"请求sip服务中" );
        }

        @Override
        public void onRegistrationDone(String s, long l) {
            Api.isRegistering = true;
            updateStatus("Ready");
            Log.e(TAG, "onRegistrationDone: "+"sip注册成功" );
        }

        @Override
        public void onRegistrationFailed(String s, int i, String s1) {
            Api.isRegistering = false;
            updateStatus("注册失败，请检查sip账号密码和IP地址是否正确");
            Log.e(TAG, "onRegistrationFailed: "+s );
            Log.e(TAG, "onRegistrationFailed: "+i );
            Log.e(TAG, "onRegistrationFailed: "+s1 );
            Log.e(TAG, "onRegistrationFailed: "+"sip注册失败" );
        }
    };

    /**
     * 拨打电话监听
     */
    private final SipAudioCall.Listener listener = new SipAudioCall.Listener(){
        //准备打电话
        @Override
        public void onReadyToCall(SipAudioCall call) {
            Log.e(TAG, "onReadyToCall: " );
        }

        @Override
        public void onRinging(SipAudioCall call, SipProfile caller) {
            Log.e(TAG, "onRinging: ");
        }

        @Override
        public void onCallEstablished(SipAudioCall call) {
            //启动来电弹窗
            new AlertDialog.Builder(MainActivity.this)
                    .setTitle("网络来电")
                    .setMessage(call.getPeerProfile().getUriString())
                    .setPositiveButton("接听", (dialogInterface, i) -> {
                        //启动音频
                        call.startAudio();
                        //设置为扬声器模式,也就是开启回声抑制
                        call.setSpeakerMode(false);
                        //不静音
                        updateStatus(call);
                        //必须用下面这样的写法，否则没有任何声音
                        if(call.isMuted()) {
                            call.toggleMute();
                        }
                        updateStatus("通话中...");
                        Log.e(TAG, "onCallEstablished: 内端口"+  me.getPort() );
                    })
                    .setNegativeButton("挂断", (dialogInterface, i) -> {
                        try {
                            call.endCall();
                        } catch (SipException e) {
                            e.printStackTrace();
                        }
                    }).show();

        }

        @Override
        public void onCallEnded(SipAudioCall call) {
            Log.e(TAG, "onCallEnded: " );
            updateStatus("Ready....");
        }
    };


    ///////////////////////////////////////////////////////////////////////


    @Override
    protected void onStart() {
        super.onStart();
        //注册广播
        registerInComingCallReceiver();
        //注册SipManager
        initializeManager();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        navigationView = findViewById(R.id.nav_view);

        //网络监测
        if (!MySystemUtil.isNetworkAvailable(this)){
            Toast.makeText(this,"暂无网络连接",Toast.LENGTH_SHORT).show();
        }
        //申请sip、录音权限
        verifyAudioPermissions(this);

        //初始化view
        initView();
    }

    //////////////////////////////////////////////////////////////////

    /**
     * 注册广播
     */
    private void registerInComingCallReceiver() {
        IntentFilter filter = new IntentFilter();
        filter.addAction("android.SipDemo.INCOMING_CALL");
        callReceiver = new IncomingCallReceiver();
        this.registerReceiver(callReceiver, filter);
    }

    /**
     * 初始化布局
     */
    private void initView() {
        //实例化Fragment
        StartFragment startFragment = new StartFragment();
        CenterFragment centerFragment = new CenterFragment();
        EndFragment endFragment = new EndFragment();
        //组成数组
        fragments = new Fragment[]{startFragment, centerFragment, endFragment};
        //初始化视图
        lastFragment = 0;
        getSupportFragmentManager().beginTransaction().replace(R.id.nav_host_frameLayout,startFragment)
                .show(startFragment).commit();
        //绑定底部菜单栏监听
        navigationView.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
    }

    /**
     * sipManager注册
     */
    private void initializeManager() {
        //实例化
        if(manager == null) {
            Log.e(TAG, "initializeManager: 注册");
            manager = SipManager.newInstance(this);
        }
        initializeLocalProfile();
    }



    /**
     * 权限申请
     * @param activity 活动
     */
    private static void verifyAudioPermissions(Activity activity) {
        Log.e(TAG, "verifyAudioPermissions: 开始权限申请");
        int permission = ActivityCompat.checkSelfPermission(activity,
                Manifest.permission.USE_SIP);
        int permissionAudio = ActivityCompat.checkSelfPermission(activity,
                Manifest.permission.RECORD_AUDIO);
        int permissionSdk = ActivityCompat.checkSelfPermission(activity,
                Manifest.permission.WRITE_EXTERNAL_STORAGE);

        if (permission != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(activity, PERMISSION_SIP,1);
        }else {
            Log.e(TAG, "verifyAudioPermissions: sip权限已开启");
        }
        if (permissionAudio != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(activity, PERMISSION_AUDIO,1);
        }else {
            Log.e(TAG, "verifyAudioPermissions: 录音权限已开启");
        }
        if (permissionSdk != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(activity, PERMISSION_SDK,1);
        }else {
            Log.e(TAG, "verifyAudioPermissions: sdk权限已开启");
        }
    }

    ///////////////////////////////////////////////////////////////////////////////

    /**
     * 登录用户本地信息
     */
    private void initializeLocalProfile() {
        if (manager == null) {
            manager = SipManager.newInstance(this);
            Toast.makeText(this,"当前设备不支持sip电话",Toast.LENGTH_SHORT).show();
            updateStatus("当前设备不支持sip");
            Log.e(TAG, "initializeManager: 实例化失败");
            return;
        }
        if (me != null) {
            closeLocalProfile();
        }
        //获取本地登录信息
        //uesrname表示注册用户名,domain表示域,实际就是sip服务器ip,password即账号密码
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
        String username = prefs.getString("namePref", "").trim();
        String domain = prefs.getString("domainPref", "").trim();
        String password = prefs.getString("passPref", "").trim();

        //判断本地是否有登录信息,没有则退出
        if ("-1".equals(username) || "-1".equals(domain) || "-1".equals(password)) {
            Log.e(TAG, "initializeLocalProfile: 未登录");
            //弹窗让用户登录填写sip账户和地址
            showDialog(UPDATE_SETTINGS_DIALOG);
            return;
        }
        //有本地登录信息拼接组成本地sipProfile
        try {
            Log.e(TAG, "initializeLocalProfile: 拼接sipProfile");
            //地址格式不能填错
            SipProfile.Builder builder = new SipProfile.Builder(username,domain);
            builder.setPassword(password);
            builder.setPort(5060);
            builder.setAutoRegistration(true);
            me = builder.build();

            //添加一个本地的过滤器，用于接受电话
            //构造一个PendingIntent对象,这样当sip Service收到一个通话请求时,
            //SipService会调用PendingIntent的send方法发送相应广播消息给调用者,也就是当前的SipProfile对象.
            Intent intent = new Intent();
            intent.setAction("android.SipDemo.INCOMING_CALL");
            PendingIntent pi = PendingIntent.getBroadcast(this, 0, intent, Intent.FILL_IN_DATA);
            Log.e(TAG, "initializeLocalProfile: 拼接sipProfile结束");
            //注册并监听
            manager.open(me, pi, registrationListener);
        } catch (ParseException pe) {
            Log.e(TAG, " new SipProfile.Builder: 失败");
            pe.printStackTrace();
            updateStatus("Connection Error");
        } catch (SipException se) {
            Log.e(TAG, "manager.open: 失败");
            se.printStackTrace();
            updateStatus("Connection error");
        }
    }


    /**
     * 关闭sipProfile并释放内存
     */
    private void closeLocalProfile() {
        if (manager == null) {
            return;
        }
        if (me != null) {
            try {
                manager.close(me.getUriString());
            } catch (SipException e) {
                e.printStackTrace();
            }
        }
    }



    /**
     * 开始拨号，从一个设备拨打电话到另一个设备,前提是两个设备都已注册到sip服务器
     */
    public void initiateCall(String sipAddress){
        //更新状态
        updateStatus(sipAddress);
        try {
            // makeAudioCall方法：拨打网络电话
            // me：本地设备的SipProfile对象,
            // sipAddress：目标设备的SipProfile对象,listener是监听器
            Log.e(TAG,"start audioCall");
            call = manager.makeAudioCall(me.getUriString(), sipAddress, listener, 30);
            call.toggleMute();
            Log.e(TAG,"end audioCall");
        }
        catch (Exception e) {
            if (me != null) {
                try {
                    manager.close(me.getUriString());
                } catch (Exception ee) {
                    ee.printStackTrace();
                }
            }
            if (call != null) {
                call.close();
            }
        }
    }


    /**
     * 更新通话状态
     * @param call call
     */
    private void updateStatus(SipAudioCall call) {
        String useName = call.getPeerProfile().getDisplayName();
        if(useName == null) {
            useName = call.getPeerProfile().getUserName();
        }
        updateStatus("sip:" + useName + "@" + call.getPeerProfile().getSipDomain());
    }

    /**
     * 更新UI线程
     * @param status status.
     */
    private void updateStatus(final String status) {
        this.runOnUiThread(() -> {
            Log.e("updateStatus",status);
            TextView labelView = findViewById(R.id.text_sip_status_label);
            labelView.setText(status);
        });
    }


    /**
     * 功能菜单
     * @param menu 打电话、登录、结束电话
     * @return bool
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        menu.add(0,REGISTER_AGAIN,0,"重新注册");
        menu.add(0, SET_AUTH_INFO, 0, "我的sip账户");
        menu.add(0, HANG_UP, 0, "挂断");
        return true;
    }

    /**
     * 菜单选择
     * @param item 被选中的菜单
     * @return bool
     */
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case REGISTER_AGAIN:
                //重新注册
                updateStatus("register...");
                initializeLocalProfile();
                break;
            case SET_AUTH_INFO:
                //打开登录sip弹窗
                updatePreferences();
                break;
            case HANG_UP:
                //挂断电话
                if(call != null) {
                    try {
                        call.endCall();
                    } catch (SipException se) {
                        se.printStackTrace();
                    }
                    call.close();
                }
                break;
            default:
                break;
        }
        return true;
    }

    /**
     * 系统弹窗
     * @param id id
     * @return dialog
     */
    @Override
    protected Dialog onCreateDialog(int id) {
        if (id == UPDATE_SETTINGS_DIALOG) {
            return new AlertDialog.Builder(this)
                    .setMessage("请更新您的SIP帐户设置")
                    .setPositiveButton("更新", (dialog, whichButton) -> updatePreferences())
                    .setNegativeButton("取消", null)
                    .create();
        }
        return null;
    }


    /**
     * 更新本地sip账户信息
     */
    private void updatePreferences() {
        Intent settingsActivity = new Intent(getBaseContext(), SipSettings.class);
        startActivity(settingsActivity);
    }



    @Override
    public void onDestroy() {
        super.onDestroy();
        //销毁的时候把相应开启的空间释放
        if (call != null) {
            call.close();
        }

        closeLocalProfile();

        if (callReceiver != null) {
            this.unregisterReceiver(callReceiver);
        }
    }

}
